/*
 * Copyright (C) 2020 Agrui
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IPC_SERVICE_H
#define IPC_SERVICE_H

#include <protobuf-c/protobuf-c.h>
#include "ArrayList.h"
#include "IpcResult.h"
#include "IpcType.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
    IPC_SERVICE_MGR     = 0,
    IPC_SERVICE_NAS     = 1,
    IPC_SERVICE_SIM     = 2,
} IpcServiceId;

typedef struct {
    int subId;
    int8_t channelId;
} IpcServiceClientData;

typedef struct IpcService IpcService;

typedef IPC_RESULT (*ipcRequestCallback)(IpcTransaction* transaction, void* clientData, int msgId, void* data, int dataLen);
typedef void* (*ipcUnpackBuffer)(ProtobufCAllocator *allocator, size_t len,const uint8_t* data);
typedef void (*ipcFreeUnpackBuffer)(void* message, ProtobufCAllocator *allocator);
typedef int8_t (*ipcServiceInitClient)(IpcService* service, void* clientData);


typedef struct {
    ipcServiceInitClient initClientCb;
    ipcUnpackBuffer unpackCb;
    ipcFreeUnpackBuffer freeUnpackCb;
} IpcServiceOps;

typedef struct {
    int msgId;
    ipcRequestCallback callback;
} IpcServiceDispatcher;


typedef struct IpcService{
    int serviceId;
    ArrayList* clientList;
    int clientDataSize;
    int maxClientCount;
    IpcServiceDispatcher* dispatchTable;
    int dispatchTableCount;
    IpcServiceOps ops;
} IpcService;


#define SERVICE_FROM_TRANSACTION(transaction) (IpcService*)(transaction->serviceInfo)

IpcService* newIpcService(int serviceId, ipcUnpackBuffer unpackCb, ipcFreeUnpackBuffer freeUnpackCb);

void registerDispatchTable(IpcService* service, IpcServiceDispatcher* dispatcher, int count);

int8_t IpcServiceAllocClient(IpcService* service, int8_t channelId, int8_t subId);

void IpcServiceFreeClient(IpcService* service, int8_t channelId, int8_t clientId);

IPC_RESULT dispatchRequest(IpcService* service, IpcTransaction* transaction, void* data, int dataLen);

IPC_RESULT ipcSendIndication(IpcService* service, int channelId, int msgId, void* data, int dataLen);

IPC_RESULT ipcSendResponse(IpcTransaction* transaction, IPC_RESULT result, void* data, int dataLen);

void deleteIpcService(IpcService* service);

#ifdef __cplusplus
}
#endif

#endif
